/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace DaveSexton.DocProject.Sandcastle.ContentManagement
{
	[Serializable]
	public abstract class ContentDocument
	{
		#region Public Properties
		public virtual string DisplayName
		{
			get
			{
				return System.IO.Path.GetFileNameWithoutExtension(file);
			}
		}

		public string FilePath
		{
			get
			{
				return file;
			}
		}

		public ContentItemCollection Items
		{
			get
			{
				return items;
			}
		}

		public IEnumerable<ContentItem> BaseItems
		{
			get
			{
				foreach (ContentItem item in items)
					yield return item;
			}
		}

		public bool IsDirty
		{
			get
			{
				if (isDirty)
					return true;

				foreach (ContentItem item in items)
					if (item.IsDirty)
						return true;

				return false;
			}
			internal set
			{
				isDirty = value;
			}
		}
		#endregion

		#region Private / Protected
		private bool isDirty;
		private readonly ContentItemCollection items;
		private readonly string file;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ContentDocument" /> class for derived types.
		/// </summary>
		protected ContentDocument(string file)
		{
			if (string.IsNullOrEmpty(file))
				throw new ArgumentException(Resources.Errors.NullOrEmpty, "file");

			this.file = file;
			items = new ContentItemCollection(this);
		}
		#endregion

		#region Methods
		protected internal virtual void NotifyItemChanged(ContentItem item)
		{
			isDirty = true;
			OnItemChanged(new ContentItemEventArgs(item));
		}

		public abstract ContentItem CreateItem(string name);

		public abstract void Load(DaveSexton.Controls.Importer rebaseTargetDirectory);

		public abstract void Commit();

		public abstract void Cancel();

		public abstract void Save();

		public abstract void Save(string targetPath);
		#endregion

		#region Events
		private readonly object ItemChangedEventLock = new object();
		private EventHandler<ContentItemEventArgs> ItemChangedEvent;

		/// <summary>
		/// Event raised when a <see cref="ContentItem"/> changes.
		/// </summary>
		public event EventHandler<ContentItemEventArgs> ItemChanged
		{
			add
			{
				lock (ItemChangedEventLock)
				{
					ItemChangedEvent += value;
				}
			}
			remove
			{
				lock (ItemChangedEventLock)
				{
					ItemChangedEvent -= value;
				}
			}
		}

		/// <summary>
		/// Raises the <see cref="ItemChanged" /> event.
		/// </summary>
		/// <param name="e"><see cref="ContentItemEventArgs" /> object that provides the arguments for the event.</param>
		protected virtual void OnItemChanged(ContentItemEventArgs e)
		{
			EventHandler<ContentItemEventArgs> handler = null;

			lock (ItemChangedEventLock)
			{
				handler = ItemChangedEvent;
			}

			if (handler != null)
				handler(this, e);
		}
		#endregion
	}

	/// <summary>
	/// Provides event arguments for the <see cref="ContentDocument"/> class.
	/// </summary>
	[Serializable]
	public class ContentItemEventArgs : EventArgs
	{
		#region Public Properties
		public ContentItem Item
		{
			get
			{
				return item;
			}
		}
		#endregion

		#region Private / Protected
		private readonly ContentItem item;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="ContentItemEventArgs" /> class.
		/// </summary>
		public ContentItemEventArgs(ContentItem item)
		{
			if (item == null)
				throw new ArgumentNullException("item");

			this.item = item;
		}
		#endregion
	}
}
